package com.hup.minicontroller.common.netty.handler;

import android.util.Log;

import com.hup.minicontroller.common.netty.NettyConstant.DataType;
import com.hup.minicontroller.common.netty.model.LoginRequestPacket;
import com.hup.minicontroller.common.netty.model.LoginResponsePacket;

import java.lang.reflect.Modifier;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey;

/**
 * 客户端的登陆认证处理器
 *
 * @author hugan
 * @date 2021/5/1
 */
@Sharable
public abstract class LoginResponseHandler<T extends LoginRequestPacket, R extends LoginResponsePacket> extends ChannelInboundHandlerAdapter {
    private static final String TAG = LoginResponseHandler.class.getSimpleName();
    private static final AttributeKey<LoginResponsePacket> LOGIN_SUCCESS_RESPONSE_DATA = AttributeKey.newInstance("LOGIN_SUCCESS_RESPONSE_DATA");

    @Override
    @SuppressWarnings("unchecked")
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //Log.i(TAG, "channelRead: " + msg);
        Channel channel = ctx.channel();
        R loginRes;
        try {
            loginRes = (R) msg;
        } catch (Exception e) {
            Log.d(TAG, "channelRead: 登陆认证回复数据异常=" + msg + ", " + channel.remoteAddress());
            ctx.channel().close();
            return;
        }
        onLoginResponse(channel, loginRes);
        ctx.pipeline().remove(this);//收到回复后,移除本处理器
        super.channelRead(ctx, loginRes);//传递给后面的处理器,由它们处理success结果判断功能
    }

    /**
     * 获取登陆回复的Class,用于注册解码 {@link LoginResponsePacket}
     */
    public abstract Class<R> getLoginResponseType();

    /**
     * 获取登陆请求数据
     */
    public abstract T getLoginValidData();

    /**
     * 收到服务端认证回复后保存attr
     *
     * @param data {@link LoginResponsePacket#isSuccess()} 不一定是认证成功的
     */
    private void onLoginResponse(Channel channel, R data) {
        channel.attr(LOGIN_SUCCESS_RESPONSE_DATA).set(data);
    }

    @SuppressWarnings("unchecked")
    public R getLoginResponseData(Channel channel) {
        return (R) channel.attr(LOGIN_SUCCESS_RESPONSE_DATA).get();
    }

    /**
     * @return 是否收到服务端认证成功的回复
     */
    public static boolean isLoginResponseSuccess(Channel channel) {
        LoginResponsePacket responsePacket = channel.attr(LOGIN_SUCCESS_RESPONSE_DATA).get();
        return responsePacket != null && responsePacket.isSuccess();
    }

    /**
     * 处理 {@link LoginResponsePacket}的解码功能;
     * 在绑定 {@link LoginResponseHandler}时调用
     */
    public static void handleLoginResponseCodec(LoginResponseHandler<?, ?> loginResponseHandler) {
        if (loginResponseHandler != null) {
            Class<? extends LoginResponsePacket> responseType = loginResponseHandler.getLoginResponseType();
            int modifiers = responseType.getModifiers();
            if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers)) {
                throw new IllegalArgumentException("传入的[LoginResponsePacket]必须是实现类,不能为抽象类或接口:" + responseType);
            }
            DataCodecHandler.INSTANCE.registerType(responseType);
        } else {
            DataCodecHandler.INSTANCE.unRegisterType(DataType.LOGIN_RESPONSE);
        }
    }
}
